#include "GY_ButtonItem.h"
#include <QDebug>

GY_ButtonItem::GY_ButtonItem(const QString &guid, QGraphicsItem *parent) : GY_ContainerTransform(guid,this, parent)
{
    initializationPropertyInfo();
    this->setCenterPointF(m_PropertyInfoMap["position"].propertyValue.toPointF());
    QPen pen;
    pen.setColor(Qt::red);
    pen.setStyle(Qt::DotLine);
    m_pRect = new GY_GraphicsButtonEditItem(this);
    m_pRect->setPen(pen);
    this->addToGroup(m_pRect);
    connect(m_pRect,&GY_GraphicsButtonEditItem::doubleClicked,[=] () {
        int currentState = m_PropertyInfoMap["CurrentState"].propertyValue.toInt();
        if(currentState == m_PropertyInfoMap["NumberOfStates"].propertyValue.toInt()) {
            currentState = 1;
        }else {
            currentState++;
        }
        updateCurrentState("CurrentState",currentState);
    });
    m_pRect->setZValue(99999);
    updatePath();
}

GY_ButtonItem::~GY_ButtonItem()
{

}

bool GY_ButtonItem::addItem(GY_Object *pItem)
{
    if(pItem->inherits("GY_BasicsGraphicsObject"))
    {
        this->addToGroup((GY_BasicsGraphicsObject*)pItem);
        if(!m_PropertyInfoMap["ShowAllStates"].propertyValue.toBool()) {
            ((GY_BasicsGraphicsObject*)pItem)->setVisible(false);
        }
    }
    else if(pItem->inherits("GY_ContainerTransform"))
    {
        this->addToGroup((GY_ContainerTransform*)pItem);
        if(!m_PropertyInfoMap["ShowAllStates"].propertyValue.toBool()) {
            ((GY_ContainerTransform*)pItem)->setVisible(false);
        }
    }
    else
    {
        return false;
    }
    m_OrderChildrens.append(pItem);
    m_ChildrensMap.insert(pItem->getGuid(),pItem);
    m_PropertyInfoMap["NumberOfStates"].propertyValue = m_OrderChildrens.size();
    return true;
}

bool GY_ButtonItem::removItem(const QString &guid)
{
    if(!m_ChildrensMap.contains(guid))
    {
        return false;
    }
    m_ChildrensMap.remove(guid);
    return true;
}

bool GY_ButtonItem::removItem(const GY_Object *pItem)
{
    if(pItem->inherits("GY_BasicsGraphicsObject"))
    {
        this->removeFromGroup((GY_BasicsGraphicsObject*)pItem);
    }
    else if(pItem->inherits("GY_ContainerTransform"))
    {
        this->removeFromGroup((GY_ContainerTransform*)pItem);
    }
    else
    {
        return false;
    }
    m_OrderChildrens.removeOne((GY_Object *)pItem);
    m_PropertyInfoMap["NumberOfStates"].propertyValue = m_OrderChildrens.size();
    return  removItem(pItem->getGuid());
}

void GY_ButtonItem::initializationPropertyInfo()
{
    GY_PropertyInfo ObjectName(this);
    ObjectName.propertyName = "ObjectName";
    ObjectName.propertyValue = QString();
    ObjectName.updateType = Update|OrdinaryAttributes;
    ObjectName.propertyType = QStringPropertyType;
    ObjectName.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updateObjectName;
    m_PropertyInfoMap.insert("ObjectName",ObjectName);
    m_PropertyInfoMap[ObjectName.propertyName].setConnect();

    //位置
    GY_PropertyInfo positonPropertyInfo(this);
    positonPropertyInfo.propertyName="Position";
    positonPropertyInfo.propertyValue=QPointF(0,0);
    positonPropertyInfo.updateType = Update|MoveUpdate|PointOfRelative;
    positonPropertyInfo.propertyType = PointPropertyType;
    positonPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updatePosition;
    m_PropertyInfoMap.insert(positonPropertyInfo.propertyName,positonPropertyInfo);
    m_PropertyInfoMap[positonPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo Point1PropertyInfo(this);
    Point1PropertyInfo.propertyName="Point1";
    Point1PropertyInfo.propertyValue=QPointF(-60,-30);
    Point1PropertyInfo.updateType = NotUpdate;
    Point1PropertyInfo.propertyType = PointPropertyType;
    Point1PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updatePoint1;
    m_PropertyInfoMap.insert(Point1PropertyInfo.propertyName,Point1PropertyInfo);
    m_PropertyInfoMap[Point1PropertyInfo.propertyName].setConnect();

    GY_PropertyInfo Point2PropertyInfo(this);
    Point2PropertyInfo.propertyName="Point2";
    Point2PropertyInfo.propertyValue=QPointF(60,-30);
    Point2PropertyInfo.updateType = NotUpdate;
    Point2PropertyInfo.propertyType = PointPropertyType;
    Point2PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updatePoint2;
    m_PropertyInfoMap.insert(Point2PropertyInfo.propertyName,Point2PropertyInfo);
    m_PropertyInfoMap[Point2PropertyInfo.propertyName].setConnect();

    GY_PropertyInfo Point3PropertyInfo(this);
    Point3PropertyInfo.propertyName="Point3";
    Point3PropertyInfo.propertyValue=QPointF(60,30);
    Point3PropertyInfo.updateType = NotUpdate;
    Point3PropertyInfo.propertyType = PointPropertyType;
    Point3PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updatePoint3;
    m_PropertyInfoMap.insert(Point3PropertyInfo.propertyName,Point3PropertyInfo);
    m_PropertyInfoMap[Point3PropertyInfo.propertyName].setConnect();

    GY_PropertyInfo Point4PropertyInfo(this);
    Point4PropertyInfo.propertyName="Point4";
    Point4PropertyInfo.propertyValue=QPointF(-60,30);
    Point4PropertyInfo.updateType = NotUpdate;
    Point4PropertyInfo.propertyType = PointPropertyType;
    Point4PropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updatePoint4;
    m_PropertyInfoMap.insert(Point4PropertyInfo.propertyName,Point4PropertyInfo);
    m_PropertyInfoMap[Point4PropertyInfo.propertyName].setConnect();

    GY_PropertyInfo activeAreaLeft(this);
    activeAreaLeft.propertyName = "ActiveArea.Left";
    activeAreaLeft.propertyValue = -60;
    activeAreaLeft.updateType = Update|OrdinaryAttributes;
    activeAreaLeft.propertyType = QrealPropertyType;
    activeAreaLeft.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updateActiveAreaLeft;
    m_PropertyInfoMap.insert(activeAreaLeft.propertyName,activeAreaLeft);
    m_PropertyInfoMap[activeAreaLeft.propertyName].setConnect();

    GY_PropertyInfo activeAreaRight(this);
    activeAreaRight.propertyName = "ActiveArea.Right";
    activeAreaRight.propertyValue = 60;
    activeAreaRight.updateType = Update|OrdinaryAttributes;
    activeAreaRight.propertyType = QrealPropertyType;
    activeAreaRight.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updateActiveAreaRight;
    m_PropertyInfoMap.insert(activeAreaRight.propertyName,activeAreaRight);
    m_PropertyInfoMap[activeAreaRight.propertyName].setConnect();

    GY_PropertyInfo activeAreaBottom(this);
    activeAreaBottom.propertyName = "ActiveArea.Bottom";
    activeAreaBottom.propertyValue = -30;
    activeAreaBottom.updateType = Update|OrdinaryAttributes;
    activeAreaBottom.propertyType = QrealPropertyType;
    activeAreaBottom.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updateActiveAreaBottom;
    m_PropertyInfoMap.insert(activeAreaBottom.propertyName,activeAreaBottom);
    m_PropertyInfoMap[activeAreaBottom.propertyName].setConnect();

    GY_PropertyInfo activeAreaTop(this);
    activeAreaTop.propertyName = "ActiveArea.Top";
    activeAreaTop.propertyValue = 30;
    activeAreaTop.updateType = Update|OrdinaryAttributes;
    activeAreaTop.propertyType = QrealPropertyType;
    activeAreaTop.updatePropertyFun = (GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updateActiveAreaTop;
    m_PropertyInfoMap.insert(activeAreaTop.propertyName,activeAreaTop);
    m_PropertyInfoMap[activeAreaTop.propertyName].setConnect();

    GY_PropertyInfo currentStatePropertyInfo(this);
    currentStatePropertyInfo.propertyName="CurrentState";
    currentStatePropertyInfo.propertyValue=0;
    currentStatePropertyInfo.updateType = Update|OrdinaryAttributes;
    currentStatePropertyInfo.propertyType = UshortPropertyType;
    currentStatePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updateCurrentState;
    m_PropertyInfoMap.insert(currentStatePropertyInfo.propertyName,currentStatePropertyInfo);
    m_PropertyInfoMap[currentStatePropertyInfo.propertyName].setConnect();

    GY_PropertyInfo showAllStatesPropertyInfo(this);
    showAllStatesPropertyInfo.propertyName="ShowAllStates";
    showAllStatesPropertyInfo.propertyValue=false;
    showAllStatesPropertyInfo.updateType = Update|OrdinaryAttributes;
    showAllStatesPropertyInfo.propertyType = BoolPropertyType;
    showAllStatesPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updateShowAllStates;
    m_PropertyInfoMap.insert(showAllStatesPropertyInfo.propertyName,showAllStatesPropertyInfo);
    m_PropertyInfoMap[showAllStatesPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo numberOfStatesPropertyInfo(this);
    numberOfStatesPropertyInfo.propertyName="NumberOfStates";
    numberOfStatesPropertyInfo.propertyValue=0;
    numberOfStatesPropertyInfo.updateType = Update|OrdinaryAttributes;
    numberOfStatesPropertyInfo.propertyType = UshortPropertyType;
    numberOfStatesPropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updateNumberOfStates;
    m_PropertyInfoMap.insert(numberOfStatesPropertyInfo.propertyName,numberOfStatesPropertyInfo);
    m_PropertyInfoMap[numberOfStatesPropertyInfo.propertyName].setConnect();

    GY_PropertyInfo isVisiblePropertyInfo(this);
    isVisiblePropertyInfo.propertyName="IsVisible";
    isVisiblePropertyInfo.propertyValue=true;
    isVisiblePropertyInfo.updateType = Update|OrdinaryAttributes;
    isVisiblePropertyInfo.propertyType = BoolPropertyType;
    isVisiblePropertyInfo.updatePropertyFun=(GY_PropertyInfo::UpdatePropertyFun)&GY_ButtonItem::updateIsVisible;
    m_PropertyInfoMap.insert(isVisiblePropertyInfo.propertyName,isVisiblePropertyInfo);
    m_PropertyInfoMap[isVisiblePropertyInfo.propertyName].setConnect();

}

bool GY_ButtonItem::updatePosition(const QString &name, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    //setpos设置为父级坐标
    QPointF point = value.toPointF();
    if(this->parentItem()) {
        point = this->mapToParent(this->mapFromScene(value.toPointF()));
    }
    this->setPos(point);
    m_PropertyInfoMap[name].propertyValue=this->mapFromScene(value.toPointF());
    return true;
}

bool GY_ButtonItem::updatePoint1(const QString &, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF position = this->mapToScene(m_PropertyInfoMap["position"].propertyValue.toPointF());
    m_PropertyInfoMap["ActiveArea.Left"].propertyValue = value.toPointF().x()-position.x();
    m_PropertyInfoMap["ActiveArea.Bottom"].propertyValue = value.toPointF().y()-position.y();
    updatePath();
    return true;
}

bool GY_ButtonItem::updatePoint2(const QString &, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF position = this->mapToScene(m_PropertyInfoMap["position"].propertyValue.toPointF());
    m_PropertyInfoMap["ActiveArea.Right"].propertyValue = value.toPointF().x()-position.x();
    m_PropertyInfoMap["ActiveArea.Bottom"].propertyValue = value.toPointF().y()-position.y();
    updatePath();
    return true;
}

bool GY_ButtonItem::updatePoint3(const QString &, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF position = this->mapToScene(m_PropertyInfoMap["position"].propertyValue.toPointF());
    m_PropertyInfoMap["ActiveArea.Right"].propertyValue = value.toPointF().x()-position.x();
    m_PropertyInfoMap["ActiveArea.Top"].propertyValue = value.toPointF().y()-position.y();
    updatePath();
    return true;
}

bool GY_ButtonItem::updatePoint4(const QString &, const QVariant &value)
{
    if(!value.canConvert<QPointF>())
    {
        return false;
    }
    QPointF position = this->mapToScene(m_PropertyInfoMap["position"].propertyValue.toPointF());
    m_PropertyInfoMap["ActiveArea.Left"].propertyValue = value.toPointF().x()-position.x();
    m_PropertyInfoMap["ActiveArea.Top"].propertyValue = value.toPointF().y()-position.y();
    updatePath();
    return true;
}

bool GY_ButtonItem::updateCurrentState(const QString &name, const QVariant &value)
{
    if(!value.canConvert<ushort>())
    {
        return false;
    }
    int m_OrderChildrensSize = m_OrderChildrens.size();
    if(value.toUInt()>(ushort)m_OrderChildrensSize) {
        m_PropertyInfoMap[name].propertyValue=(ushort)m_OrderChildrensSize;
    }else {
        m_PropertyInfoMap[name].propertyValue=value.toUInt();
    }
    if(!m_PropertyInfoMap["ShowAllStates"].propertyValue.toBool()) {
        for(int i = 0; i<m_OrderChildrensSize; i++) {
            hideItem(i);
        }
        showChildrenItem(m_PropertyInfoMap[name].propertyValue.toUInt()-1);
    }
    return true;
}

bool GY_ButtonItem::updateActiveAreaLeft(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue = value;
    updatePath();
    return true;
}

bool GY_ButtonItem::updateActiveAreaRight(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue = value;
    updatePath();
    return true;
}

bool GY_ButtonItem::updateActiveAreaBottom(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue = value;
    updatePath();
    return true;
}

bool GY_ButtonItem::updateActiveAreaTop(const QString &name, const QVariant &value)
{
    if(!value.canConvert<qreal>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue = value;
    updatePath();
    return true;
}

bool GY_ButtonItem::updateIsVisible(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    m_PropertyInfoMap[name].propertyValue=value.toBool();
    this->setVisible(value.toBool());
    return true;
}

bool GY_ButtonItem::updateNumberOfStates(const QString &, const QVariant &)
{

    return false;
}

bool GY_ButtonItem::updateShowAllStates(const QString &name, const QVariant &value)
{
    if(!value.canConvert<bool>())
    {
        return false;
    }
    int m_OrderChildrensSize = m_OrderChildrens.size();
    m_PropertyInfoMap[name].propertyValue=value.toBool();
    if(value.toBool()) {
        for(int i = 0; i<m_OrderChildrensSize; i++) {
            showChildrenItem(i);
        }
    }else {
        for(int i = 0; i<m_OrderChildrensSize; i++) {
            hideItem(i);
        }
        showChildrenItem(m_PropertyInfoMap["CurrentState"].propertyValue.toUInt()-1);
    }
    return true;
}

void GY_ButtonItem::showChildrenItem(const int &index)
{
    if(index < 0) {
        return;
    }
    GY_Object *pItem = m_OrderChildrens.at(index);
    if(pItem->inherits("GY_BasicsGraphicsObject"))
    {
        ((GY_BasicsGraphicsObject*)pItem)->setVisible(true);
    }
    else if(pItem->inherits("GY_ContainerTransform"))
    {
        ((GY_ContainerTransform*)pItem)->setVisible(true);
    }
}

void GY_ButtonItem::hideItem(const int &index)
{
    if(index < 0) {
        return;
    }
    GY_Object *pItem = m_OrderChildrens.at(index);
    if(pItem->inherits("GY_BasicsGraphicsObject"))
    {
        ((GY_BasicsGraphicsObject*)pItem)->setVisible(false);
    }
    else if(pItem->inherits("GY_ContainerTransform"))
    {
        ((GY_ContainerTransform*)pItem)->setVisible(false);
    }
}

void GY_ButtonItem::updatePath()
{
    QPointF position = this->mapToScene(m_PropertyInfoMap["position"].propertyValue.toPointF());
    qreal left = m_PropertyInfoMap["ActiveArea.Left"].propertyValue.toReal();
    qreal right = m_PropertyInfoMap["ActiveArea.Right"].propertyValue.toReal();
    qreal bottom = m_PropertyInfoMap["ActiveArea.Bottom"].propertyValue.toReal();
    qreal top = m_PropertyInfoMap["ActiveArea.Top"].propertyValue.toReal();
    QPointF point1(position.x()+left,position.y()+bottom);
    QPointF point2(position.x()+right,position.y()+bottom);
    QPointF point3(position.x()+right,position.y()+top);
    QPointF point4(position.x()+left,position.y()+top);

    QMap<QVariant,QPointF> editPoints = {
        //!矩形逆时针连接点
        {"Point1",this->mapFromScene(point1)},{"Point2",this->mapFromScene(point2)},
        {"Point3",this->mapFromScene(point3)},{"Point4",this->mapFromScene(point4)}
    };
    this->setEditPointF(editPoints);

    QPainterPath path;
    path.moveTo(this->mapFromScene(point1));
    path.lineTo(this->mapFromScene(point2));
    path.lineTo(this->mapFromScene(point3));
    path.lineTo(this->mapFromScene(point4));
    path.closeSubpath();
    m_pRect->setPath(path);
}
